package com.tangding.service.dao.role;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.mongodb.client.model.Filters;
import com.tangding.common.exception.GException;
import com.tangding.common.logx.LogHelp;
import com.tangding.config.Config;
import com.tangding.service.dao.user.UserRepository;
import com.tangding.service.db.BaseMongoRepository;
import com.tangding.service.db.MongoDBOption;
import com.tangding.service.entity.role.Role;

/**
 * @description 
 *
 * @author Ranger
 * @version 2017年11月9日_上午10:05:37
 *
 */
@Repository
public class RoleRepository extends BaseMongoRepository<Role, Serializable> {

	@Autowired
	UserRepository userRepository;
	
	Map<Integer, Role> allRoles = new HashMap<>();
	
	@Override
	protected void afterInitClient() {
		option = new MongoDBOption("ACCOUNT", "role");
		
		try {
			List<Role> roles = findAll();
			roles.forEach(role -> {
				allRoles.put(role.getRoleId(), role);
			});
		} catch (GException e) {
			LogHelp.doLogAppErr(e);
			System.exit(-1);
		}
	}
	
	public Role getRole(int roleId) {
		return allRoles.get(roleId);
	}
	
	public void addRole(Role role) throws GException {
		allRoles.put(role.getRoleId(), role);
		save(role);
	}
	
	public void updateRole(Role role) {
		allRoles.put(role.getRoleId(), role);
		
		if (role.getRoleId() == Config.godRoleId) {
			return;
		}
		Document condition = new Document();
		condition.put("roleId", role.getRoleId());
		update(role, condition);
	}
	
	public Role getPRole(int roleId) {
		Role me = allRoles.get(roleId);
		if (me != null) {
			return allRoles.get(me.getpRoleId());
		}
		return me;
	}
	
	public Set<Role> getOneDownLevelChildren(Integer... roleIds) {
		return getOneDownLevelChildren(Arrays.asList(roleIds));
	}
	
	public Set<Role> getOneDownLevelChildren(List<Integer> roleIds) {
		Set<Role> roles = new HashSet<>(); 
		roleIds.forEach(roleId->{
			allRoles.forEach((id, role) -> {
				if (role.getpRoleId() == roleId) {
					roles.add(role);
				}
			});
		});
		return roles;
	}
	
	public Set<Role> getMyDownlineRoles(List<Integer> roleIds) {
		Set<Role> roles = new HashSet<>();
		for (Integer myRoleId : roleIds) {
			findDownLines(myRoleId, roles);
		}
		return roles;
	}
	
	private void findDownLines(Integer roleId, Set<Role> roles) {
		List<Integer> tempIds = new ArrayList<>();
		if (allRoles.containsKey(roleId)) {
			roles.add(allRoles.get(roleId));
			tempIds.add(roleId);
		}
		
		if (tempIds.size() > 0) {
			for (Integer id : tempIds) {
				findDownLines(id, roles);
			}
		}
	}
	
	public List<Role> findRolesByIds(List<Integer> roleIds) throws GException {
		Bson condition = Filters.in("roleId", roleIds);
		List<Role> roles = findAll(condition);
		return roles;
	}
}
